package oop.core;
import java.util.List;
import java.util.ArrayList;

import oop.core.med.Pausable;

/**
 * Scheduler handles mapping delays to UpdateableObject's
 * for notifications.
 * @author DangMH
 *
 */
public class Scheduler implements Pausable {
	private List<UpdateableObject> updateList;		// schedule of objects to update on delay
	private List<IDUpdateableObject> IDupdateList;	// schedule of ID-able objects to update on delay 
	private List<Updateable> persistentList;		// objects that update every frame
	private boolean paused;
	
	/**
	 * Empty constructor.
	 */
	public Scheduler()
	{
		updateList = new ArrayList<UpdateableObject>();
		IDupdateList = new ArrayList<IDUpdateableObject>();
		persistentList = new ArrayList<Updateable>();
		paused = false;
	}
	
	/**
	 * Notify operation to be used by the client
	 * to begin running delayed and persistent operations.
	 * Persistent operations will never be removed
	 * after execution.
	 * @param updateTime
	 */
	public void update( long updateTime )
	{
		if( paused )
		{
			return;
		}
		
		List<UpdateableObject> removals1 = new ArrayList<UpdateableObject>();
		List<IDUpdateableObject> removals2 = new ArrayList<IDUpdateableObject>();
		
		for( UpdateableObject uo : updateList )
		{
			if( uo.update( updateTime ) )
			{
				removals1.add( uo );
			}
		}
		
		for( UpdateableObject uo : removals1 )
		{
			updateList.remove( uo );
		}
		
		synchronized(Scheduler.class) {
			for( IDUpdateableObject uo : IDupdateList )
			{
				if( uo.update( updateTime ) )
				{
					removals2.add( uo );
				}
			}
		}
		
		for( IDUpdateableObject uo : removals2 )
		{
			IDupdateList.remove( uo );
		}
		
		for( Updateable u : persistentList )
		{
			u.update();
		}
	}
	
	/**
	 * Encapsulates an Updateable object with a delay and ID
	 * @param u
	 * @param delay
	 */
	public void register( Updateable u, long delay )
	{
		updateList.add( new UpdateableObject( u, delay ) );
	}
	
	/**
	 * Encapsulates an IDUpdateable object with a delay and ID
	 * @param u
	 * @param delay
	 * @param ID
	 */
	public void register( IDUpdateable u, long delay, int ID )
	{
		IDupdateList.add( new IDUpdateableObject( u, delay, ID ) );
	}
	
	/**
	 * Registers the Updateable object with the persistentObjects list 
	 * @param u
	 */
	public void registerPersistent( Updateable u )
	{
		persistentList.add( u );
	}

	public void pause() {
		paused = true;
	}

	public void toggle() {
		paused = !paused;
	}

	public void unpause() {
		paused = false;
	}
}
